from amqp import spec
from django.db import transaction
from rest_framework import serializers

from goods.models import SKUImage, SKU, SKUSpecification, SPU, SpecificationOption


class SKUImageSerializer(serializers.ModelSerializer):
    """SKU图片序列化器类"""

    # 关联对象嵌套序列化
    sku = serializers.StringRelatedField(label='sku商品名称')

    sku_id = serializers.IntegerField(label='sku商品ID')

    class Meta:

        model = SKUImage

        exclude = ('create_time','update_time')

    def validate_sku_id(self,value):
        # sku商品是否存在
        try:
            sku = SKU.objects.get(id=value)
        except SKU.DoesNotExist:
            raise serializers.ValidationError('商品不存在')

        return value


    def create(self, validated_data):
        """sku商品上传图片保存"""
        # 保存上传图片记录
        sku_image = super().create(validated_data)
        sku = SKU.objects.get(id=validated_data['sku_id'])

        if not sku.default_image:
            sku.default_image = sku_image.image

            sku.save()

        return sku_image




class SKUSimpleSerializer(serializers.ModelSerializer):
    """SKU商品序列化器类"""

    class Meta:

        model = SKU

        fields = ('id','name')




class SKUSpecSerializer(serializers.ModelSerializer):
    """商品规格信息序列化器类"""
    spec_id = serializers.IntegerField(label='规格id')

    option_id = serializers.IntegerField(label='选项id')


    class Meta:
        model = SKUSpecification
        fields = ('spec_id','option_id')


class SKUSerializer(serializers.ModelSerializer):
    """SKU商品序列化器类"""

    #关联对象嵌套序列化
    spu = serializers.StringRelatedField(label='spu名称')

    category = serializers.StringRelatedField(label='三级分类名称')


    spu_id = serializers.IntegerField(label='spu编号')

    category_id = serializers.IntegerField(label='三级分类ID')


    #关联对象嵌套序列化
    specs = SKUSpecSerializer(label='商品规格信息',many=True)

    class Meta:
        model = SKU

        #排除模型的字段
        exclude = ('create_time','update_time','default_image')

    def validate(self, attrs):
        #获取spu_id
        spu_id = attrs['spu_id']

        #检查spu商品是否存在
        try:
            spu = SPU.objects.get(id=spu_id)
        except SPU.DoesNotExist:
            raise serializers.ValidationError('spu商品不存在')

        #attrs中添加第三级分类ID
        attrs['category_id'] = spu.category3_id

        #检查sku规格数据是否有效
        spu_specs = spu.specs.all()

        spec_count = spu_specs.count()

        specs = attrs['specs']




        #sku商品的规格数据是否完整
        if spec_count > len(specs):
            raise serializers.ValidationError('sku规格数据不完整')

        #sku商品的规格数据是否一致
        spu_specs_ids = [spec.id for spec in spu_specs]
        spu_specs_ids.sort()

        specs_ids = [spec.get('spec_id') for spec in specs]
        specs_ids.sort()



        if spu_specs_ids != specs_ids:

            raise serializers.ValidationError('商品规格数据有误')

        for spec in specs:

            spec_id = spec.get('spec_id')

            option_id = spec.get('option_id')


            #检查spec_id对应的规格是否包含了option_id对应的选项
            options = SpecificationOption.objects.filter(spec_id=spec_id)

            options_ids = [option.id for option in options]

            if option_id not in options_ids:
                raise serializers.ValidationError('规格选项数据有误')

        return attrs


    def create(self, validated_data):
        """保存sku商品数据"""
        specs = validated_data.pop('specs')

        with transaction.atomic():
            #with语句块下的代码,操作数据库时,和数据库操作相关的代码都会

            #调用父类方法新增sku商品
            sku = SKU.objects.create(**validated_data)

            #保存商品规格信息
            for spec in specs:


                spec_id = spec.get('spec_id')

                option_id = spec.get('option_id')

                SKUSpecification.objects.create(

                    sku = sku,

                    spec_id=spec_id,

                    option_id=option_id
                )

        return sku



    def update(self, instance, validated_data):


        specs = validated_data.pop('specs')

        sku_specs_client = [spec for spec in specs]
        sku_specs_client = sorted(sku_specs_client, key=lambda a:a["option_id"])

        with transaction.atomic():


            sku = super().update(instance, validated_data)

            sku_specs = [{'spec_id':sku_spec.spec_id,
                          'option_id':sku_spec.option_id
                          }for sku_spec in sku.specs.all()]

            sku_specs = sorted(sku_specs, key=lambda a: a["option_id"])

            if sku_specs_client != sku_specs:

                sku.specs.all().delete()

                for spec in specs:

                    spec_id = spec.get('spec_id')
                    option_id = spec.get('option_id')

                    SKUSpecification.objects.create(

                        sku = sku,

                        spec_id=spec_id,

                        option_id=option_id
                    )

        return instance








